/*
 * TDA_DNS.c
 *
 *  Created on: Nov 21, 2013
 *      Author: enano
 */


#include <stdio.h>
#include <stdlib.h>
#include "TDA_DNS.h"

#define CSTR_FIN 1
#define STR_EQUAL 0
#define ZERO 0
#define DOM_NUEVO 1
#define DOM_EXISTE 2

typedef enum { DNS_Crear, DNS_Usar } modoParseo;

int DNS_Comparar(void* I, void* D)
{   elemArbol a, b;

    a = *( (elemArbol*) I); b = *( (elemArbol*) D);

    if( strcmp( a.dominio, b.dominio ) > ZERO ) return I_MAY_D;

    if( strcmp( a.dominio, b.dominio ) < ZERO ) return D_MAY_I;

    return IGUALES;
}


int parsearDominio (const char* dominio, TListaSimple* subDominios, modoParseo mode )
{/* parsea el dominio, en subdominios y los devuelve en una lista simple
  * SIEMPRE debe usarse después la funcion: vaciarDomP() */

    char *token, *subDom;
    char *domAux;
    size_t strLong, domLong;

    if ( dominio == NULL ) return ERROR;

    L_Crear( subDominios, sizeof(char*) );

    domLong = strlen(dominio)+CSTR_FIN;
    domAux = (char*) malloc( domLong * sizeof(char) );
    strncpy( domAux, dominio, domLong );

    token = strtok( domAux, "." );
    while (token != NULL)
    {
        strLong = strlen(token)+CSTR_FIN;
        subDom = ( char* ) malloc ( strLong * sizeof(char) );
        strncpy( subDom, token, strLong);
        //L_Insertar_Cte( subDominios, L_Anterior, &subDom );
        /**/
            if ( mode == DNS_Usar )
                L_Insertar_Cte( subDominios, L_Anterior, &subDom );
            else //mode == DNS_Crear
                L_Insertar_Cte( subDominios, L_Siguiente, &subDom );
        /**/
        token = strtok (NULL, ".");
    }

    free(domAux);
    L_Mover_Cte(subDominios, L_Primero);

    return OK;
}


void _testImprimirDomP ( TListaSimple* subDominios )
{/* solo para pruebas, imprime los subdominios*/

    char* elem;
    int movio;

    L_Mover_Cte(subDominios, L_Primero);
    do
    {
        L_Elem_Cte( *subDominios, &elem);
        fprintf(stdout,"elem: %s\n", elem);
        movio = L_Mover_Cte( subDominios, L_Siguiente );

    }while ( movio == TRUE );

    return;
}

void _testRecorrerArbol ( TABO abo )
{   elemArbol elem;

    if ( ABO_MoverCte(&abo, IZQ) == TRUE )
    {
        _testRecorrerArbol( abo );
        ABO_MoverCte(&abo, PAD);
    }

    ABO_ElemCte( abo, &elem );
    if ( ABO_Vacio( &(elem.subarbol) ) == FALSE )
    {
        ABO_MoverCte( &(elem.subarbol), RAIZ );
        _testRecorrerArbol( elem.subarbol );
    }
    else
    {
        fprintf(stdout, "Dominio: %s\n", elem.dominio);
        fprintf(stdout, "IP: %s\n", (char*) elem.data);
        fprintf(stdout, "Subarbol: Vacio\n\n");
    }


    if ( ABO_MoverCte( &abo, DER) == TRUE )
    {
        _testRecorrerArbol( abo );
    }

}

void _testContenidoDNS( TDADNS dns )
{
    elemArbol elem;
    int entro;

    L_Mover_Cte( &(dns.dominios), L_Primero );

    while ( L_Vacia(dns.dominios) != FALSE )
    {
       L_Elem_Cte( dns.dominios, &elem );

       entro = ABO_MoverCte( &(elem.subarbol), RAIZ );
       if ( entro == TRUE )
            _testRecorrerArbol( elem.subarbol );

       fprintf(stdout, "Dominio: %s\n", elem.dominio);
       fprintf(stdout, "IP: %s\n", (char*) elem.data);
       if ( entro == FALSE )
            fprintf(stdout, "Subarbol: Vacio\n\n");
       else
           fprintf(stdout, "\n");

       L_Mover_Cte( &(dns.dominios), L_Siguiente);
    }

    return;
}


int vaciarDomP ( TListaSimple* subDominios )
{/* Libera la memoria que se utiliza para parsear el dominio */

    char* elem;

    L_Mover_Cte(subDominios, L_Primero);
    while ( L_Vacia( *subDominios ) == FALSE )
    {
        L_Elem_Cte( *subDominios, &elem);
        free(elem);
        L_Borrar_Cte( subDominios );
    }

    return OK;
}


int buscarDominioArbol(TABO* arbolDNS, TListaSimple subDoms, elemArbol* elem)
{/* Para poder hacer Recursividad con el arbol, se usa dentro de buscarDominio */

    char* subDom;
    elemArbol ab;
    int resultado;

    if ( ABO_Vacio( arbolDNS ) == TRUE ) return DOM_INEXISTENTE;

    L_Elem_Cte( subDoms, &subDom );

    ABO_ElemCte( *arbolDNS, &ab );


    if ( strcmp( ab.dominio, subDom ) == STR_EQUAL  )
    {
        if ( L_Mover_Cte( &subDoms, L_Siguiente ) == TRUE )   /* lista de subdominios parseados */
        {
            ABO_MoverCte( &ab.subarbol, RAIZ );
            buscarDominioArbol( &ab.subarbol, subDoms, elem );
        }
        else
        {
            if ( ab.data == NULL )
                return DOM_VACIO;
            else
                memcpy( elem, &ab, sizeof(elemArbol) );
        }
    }
    else
    {
        if ( strcmp( ab.dominio, subDom ) > ZERO )
        {
            resultado = ABO_MoverCte( arbolDNS, IZQ );
        }
        else
        {
            resultado = ABO_MoverCte( arbolDNS, DER );
        }

        if ( resultado == FALSE) return DOM_INEXISTENTE;

        buscarDominioArbol( arbolDNS, subDoms, elem );
    }

    return OK;
}


void elimInfoDomArbol(TABO* arbolDNS, TListaSimple subDoms)
{/* Para poder hacer Recursividad con el arbol, se usa dentro de buscarDominio */

    char* subDom;
    elemArbol ab;
    int resultado;

    L_Elem_Cte( subDoms, &subDom );

    if ( ABO_Vacio( arbolDNS ) == TRUE ) return;

    ABO_ElemCte( *arbolDNS, &ab );


    if ( strcmp( ab.dominio, subDom ) == STR_EQUAL  )
    {
        if ( L_Mover_Cte( &subDoms, L_Siguiente ) == TRUE )   /* lista de subdominios parseados */
            elimInfoDomArbol( arbolDNS, subDoms );
        else
        {
            ABO_ElemCte( *arbolDNS, &ab );
            free(ab.data);
            ab.data = NULL;
            ABO_ModifCte( arbolDNS, &ab );
        }

    }
    else
    {
        if ( strcmp( ab.dominio, subDom ) > ZERO )
        {
            resultado = ABO_MoverCte( arbolDNS, IZQ );
        }
        else
        {
            resultado = ABO_MoverCte( arbolDNS, DER );
        }

        if ( resultado == FALSE) return;

        elimInfoDomArbol( arbolDNS, subDoms );
    }

    return;
}

void eliminarInfoDom( TListaSimple *listaDNS, TListaSimple subDoms )
{   char *subDom;
    elemArbol aux;

    L_Mover_Cte( listaDNS, L_Primero ); /* lista interna de TDADNS */
    L_Elem_Cte( *listaDNS,  &aux);

    L_Elem_Cte( subDoms, &subDom ); /* lista de subdominios parseados */

    while( strcmp( aux.dominio, subDom ) != STR_EQUAL  )
    {
        if ( L_Mover_Cte( listaDNS, L_Siguiente ) == FALSE ) return;
        L_Elem_Cte( *listaDNS,  &aux);

    }

    if ( L_Mover_Cte( &subDoms, L_Siguiente ) == TRUE )   /* lista de subdominios parseados */
    {
        ABO_MoverCte( &(aux.subarbol), RAIZ );
        elimInfoDomArbol( &(aux.subarbol), subDoms );
    }

    return;
}


int buscarDominio( TListaSimple *listaDNS, TListaSimple subDoms, elemArbol* elem )
{/* Busca un Dominio en toda la estructura de datos. Y queda apuntando a dicho subdominio.
  * RETURN:  OK, si tod0 salió bien, y devuelve la información en elem.
  *          DOM_VACIO, si existe el dominio, pero no tiene información sobre el mismo.
  *          DOM_INEXISTENTE, si no existe tal subdominio.
  **/

    char *subDom;
    elemArbol aux;
    int resultado = ERROR;

    L_Mover_Cte( listaDNS, L_Primero ); /* lista interna de TDADNS */
    L_Elem_Cte( *listaDNS,  &aux);

    L_Elem_Cte( subDoms, &subDom ); /* lista de subdominios parseados */

    while( strcmp( aux.dominio, subDom ) != STR_EQUAL  )
    {
        if ( L_Mover_Cte( listaDNS, L_Siguiente ) == FALSE ) return DOM_INEXISTENTE;
        L_Elem_Cte( *listaDNS,  &aux);

    }

    if ( L_Mover_Cte( &subDoms, L_Siguiente ) == TRUE )   /* lista de subdominios parseados */
    {
        ABO_MoverCte( &(aux.subarbol), RAIZ );
        resultado = buscarDominioArbol( &(aux.subarbol), subDoms , &aux );
    }

    memcpy( elem, &aux, sizeof(elemArbol) );

    return resultado;
}


void crearElem(char* dom, elemArbol* elem)
{   size_t LongSubDom;

    LongSubDom = strlen(dom)+CSTR_FIN;
    elem->dominio = (char*) malloc( LongSubDom * sizeof(char) );
    strncpy( elem->dominio, dom, LongSubDom );
    elem->data = NULL;
    ABO_Crear( &elem->subarbol, sizeof(elemArbol) );
    return;
}

int insertarDominioLIOrdenado( TListaSimple *listaDNS, char* subDom )
{   elemArbol elemLi, nuevo;

    if ( L_Vacia(*listaDNS) == TRUE )
    {
        crearElem( subDom, &nuevo );
        L_Insertar_Cte( listaDNS, L_Siguiente, &nuevo );
        return DOM_NUEVO;
    }

    L_Mover_Cte(listaDNS, L_Primero);
    L_Elem_Cte(*listaDNS, &elemLi);
    while ( TRUE )
    {
        if ( strcmp(elemLi.dominio, subDom) == STR_EQUAL )
            return DOM_EXISTE;
        else
            if ( strcmp(elemLi.dominio, subDom) < ZERO )
                L_Mover_Cte(listaDNS, L_Siguiente);
            else
            {
                crearElem( subDom, &nuevo);
                L_Insertar_Cte(listaDNS, L_Anterior, &nuevo);
                break;
            }
    }

    return DOM_NUEVO;
}

int insertarDominioABOrdenado( TABO* arbolDNS, TListaSimple* subDoms, void* dato, size_t tamDato )
{   char* subDom;
    elemArbol nuevo, elemAb;
    taboCmp cmp = &DNS_Comparar;

    L_Elem_Cte( *subDoms, &subDom);

    if ( ABO_Vacio( arbolDNS ) == TRUE )
    {
        crearElem( subDom, &nuevo);
        if ( L_Mover_Cte( subDoms, L_Siguiente ) == TRUE )
        {
            insertarDominioABOrdenado( &nuevo.subarbol, subDoms, dato, tamDato );
        }
        else    // L_Mover_Cte( subDoms, L_Siguiente ) == FALSE
        {
            nuevo.data = malloc( tamDato );
            memcpy( nuevo.data, dato, tamDato );
        }

        ABO_InsertarOrdenado( arbolDNS, cmp, &nuevo );
        ABO_MoverCte(arbolDNS, RAIZ);    //TODO REVISAR SI HACE FALTA.
    }
    else    // ABO_Vacio( arbolDNS ) == FALSE
    {
        ABO_ElemCte( *arbolDNS, &elemAb );

        if ( strcmp( elemAb.dominio, subDom ) == STR_EQUAL )
        {
            if ( L_Mover_Cte( subDoms, L_Siguiente ) == TRUE )
                insertarDominioABOrdenado( &elemAb.subarbol, subDoms, dato, tamDato );
            else
            {
                nuevo.data = malloc( tamDato );
                memcpy( nuevo.data, dato, tamDato );
                ABO_ModifCte( arbolDNS, &elemAb );
                ABO_MoverCte(arbolDNS, RAIZ);    //TODO REVISAR SI HACE FALTA.
            }
        }
        else if ( strcmp( elemAb.dominio, subDom ) > ZERO ) //Me muevo a la izquierda
        {
            if ( ABO_MoverCte( arbolDNS, IZQ ) == TRUE )
                insertarDominioABOrdenado( arbolDNS, subDoms, dato, tamDato );
            else
            {
                crearElem( subDom, &nuevo );
                if ( L_Mover_Cte( subDoms, L_Siguiente ) == TRUE )
                {
                    insertarDominioABOrdenado( &nuevo.subarbol, subDoms, dato, tamDato );
                }
                else    // L_Mover_Cte( subDoms, L_Siguiente ) == FALSE
                {
                    nuevo.data = malloc( tamDato );
                    memcpy( nuevo.data, dato, tamDato );
                }

                ABO_InsertarOrdenado( arbolDNS, cmp, &nuevo );
                ABO_MoverCte(arbolDNS, RAIZ);    //TODO REVISAR SI HACE FALTA.
            }
        }
        else    //strcmp( elemAb.dominio, subDom ) < ZERO - Me muevo a la derecha
        {
            if ( ABO_MoverCte(arbolDNS, DER) == TRUE )
                insertarDominioABOrdenado( arbolDNS, subDoms, dato, tamDato );
            else
            {
                crearElem( subDom, &nuevo );
                if ( L_Mover_Cte( subDoms, L_Siguiente ) == TRUE )
                {
                    insertarDominioABOrdenado( &nuevo.subarbol, subDoms, dato, tamDato );
                }
                else    // L_Mover_Cte( subDoms, L_Siguiente ) == FALSE
                {
                    nuevo.data = malloc( tamDato );
                    memcpy( nuevo.data, dato, tamDato );
                }

                ABO_InsertarOrdenado( arbolDNS, cmp, &nuevo );
                ABO_MoverCte(arbolDNS, RAIZ);    //TODO REVISAR SI HACE FALTA.
            }
        }
    }

    return OK;
}


int agregarDominio2( TDADNS* dns, char* dominio, void* dato )
{
    TListaSimple subDoms;
    char *subDom;
    elemArbol elemLis;
    int resultado;

    parsearDominio( dominio, &subDoms, DNS_Usar);

    L_Elem_Cte( subDoms, &subDom );     //lista de subdominios parseados.
    resultado = insertarDominioLIOrdenado( &(dns->dominios), subDom);

    L_Elem_Cte(dns->dominios, &elemLis);    //pido el elemento de la lista de TDADNS.

    L_Mover_Cte( &subDoms, L_Siguiente );
    resultado = insertarDominioABOrdenado( &elemLis.subarbol, &subDoms, dato, dns->tamanio );

    L_Modificar_Cte(dns->dominios, &elemLis);   //elemento de la lista de TDADNS.

    vaciarDomP(&subDoms);


    return resultado;
}


void obtenerValor( TDADNS dns, char* dominio, void* dato )
{   elemArbol elem;
    TListaSimple subDoms;
    int resultado;

    //dato = NULL;    /* si salgo con dato = NULL significa 'error' */

    if ( dominio == NULL ) return;

    if ( L_Vacia( dns.dominios ) == TRUE ) return;

    if ( parsearDominio(dominio, &subDoms, DNS_Usar) == ERROR ) return;

    resultado = buscarDominio( &(dns.dominios), subDoms, &elem );

    vaciarDomP( &subDoms );

    if ( resultado == OK )
        memcpy( dato, elem.data, dns.tamanio );
    else
        dato = NULL;

    return;
}


int existeDominio( TDADNS dns, char* dominio )
{   TListaSimple subDoms;
    elemArbol elem;
    int resultado;

    parsearDominio(dominio, &subDoms, DNS_Usar);

    resultado = buscarDominio( &(dns.dominios), subDoms, &elem );

    vaciarDomP( &subDoms );

    if ( resultado != OK ) return FALSE;

    return TRUE;

}


void eliminarDominio( TDADNS* dns, char* dominio )
{   TListaSimple subDoms;
    elemArbol elem;
    int resultado;

    parsearDominio( dominio, &subDoms, DNS_Usar);

    resultado = buscarDominio( &(dns->dominios), subDoms, &elem );

    if ( resultado != OK ) return;

    //elem.data = NULL;
    L_Mover_Cte( &subDoms, L_Primero );
    eliminarInfoDom( &dns->dominios, subDoms );

    vaciarDomP( &subDoms );

    return;
}


int crearDNS( TDADNS *dns, size_t tamDato )
{

    L_Crear( &(dns->dominios), sizeof(elemArbol) );  // lista creada
    dns->tamanio = tamDato;

    return OK;
}


int destruirArbol(TABO *abo )
{   elemArbol elem;

    if ( ABO_MoverCte(abo, IZQ) == TRUE )
    {
        destruirArbol( abo );
        ABO_MoverCte(abo, PAD);
    }

    ABO_ElemCte( *abo, &elem );
    free( elem.dominio );
    free(elem.data);
    destruirArbol( &(elem.subarbol) );

    if ( ABO_MoverCte(abo, DER) == TRUE )
    {
        destruirArbol( abo );
        ABO_MoverCte(abo, PAD);
    }

    return OK;
}

void destruirDNS ( TDADNS *dns )
{   elemArbol elem;

    L_Mover_Cte( &(dns->dominios), L_Primero );

    while ( L_Vacia(dns->dominios) != FALSE )
    {
        L_Elem_Cte( dns->dominios, &elem );
        free(elem.dominio);
        free(elem.data);
        ABO_MoverCte( &(elem.subarbol), RAIZ );
        destruirArbol( &(elem.subarbol) );
        L_Mover_Cte( &(dns->dominios), L_Siguiente);
    }

    return;
}


void obtenerEnLista( TABO elem, size_t tamElem, TListaSimple* lista )
{   elemArbol aux;
    elemInter pedido;
    size_t longStr;

    if ( ABO_Vacio( &elem ) == TRUE ) return;

    if ( ABO_MoverCte( &elem, IZQ) == TRUE )   //tod0 hacia la izquierda
    {
        obtenerEnLista( elem, tamElem, lista );
        ABO_MoverCte( &elem, PAD );
    }

    ABO_ElemCte( elem, &aux );
    //if ( ABO_Vacio( &aux.subarbol ) == FALSE )
    //    obtenerEnLista( aux.subarbol, tamElem, lista );
    if ( aux.data != NULL )                             //si tiene dato (IP) lo enlisto
    {
        longStr = strlen( aux.dominio )+CSTR_FIN;
        pedido.dominio = (char*) malloc( longStr * sizeof(char) );
        strncpy( pedido.dominio, aux.dominio, longStr );

        pedido.data = malloc( tamElem );
        memcpy( pedido.data, aux.data, tamElem );

        L_Insertar_Cte( lista, L_Siguiente, &pedido );
    }


    if ( ABO_MoverCte( &elem, DER ) == TRUE )  //tod0 hacia la derecha
    {
        obtenerEnLista( elem, tamElem, lista );
    }
}

int obtenerLista( TDADNS dns, char* dominio, TListaSimple* ls)
{
    int resultado;
    TListaSimple subDoms;
    elemArbol elemLi;

    if ( L_Vacia(*ls) == FALSE ) return FALSE;

    parsearDominio( dominio, &subDoms, DNS_Usar );

    resultado = buscarDominio( &dns.dominios, subDoms, &elemLi );

    if ( resultado == DOM_INEXISTENTE ) return FALSE;

    obtenerEnLista( elemLi.subarbol, dns.tamanio, ls );

    vaciarDomP( &subDoms );

    return TRUE;
}




int PasameUnaListaYUnTaboYYoLoOrdenoNivel3(TABO* elTabo, TListaSimple* Subdominios, void* dato, int nivel, size_t tamDato)
{
    char* sliceofDomino;
    elemArbol ElementoASerAgredado,subarbol,arbol;
    TListaSimple subarboles;
    taboCmp fptr = &DNS_Comparar;
    int i;


    if (L_Vacia(*Subdominios)==TRUE )return TRUE;
    L_Crear(&subarboles,sizeof(elemArbol));
    ABO_ElemCte(*elTabo,&subarbol);
    for(i=1;i<nivel;i++){
        L_Insertar_Cte(&subarboles,L_Siguiente,&subarbol);
        ABO_ElemCte(subarbol.subarbol,&subarbol);
    }
    L_Mover_Cte(Subdominios,L_Primero);
    L_Elem_Cte(*Subdominios,&sliceofDomino);
    L_Borrar_Cte(Subdominios);

    ABO_Crear(&ElementoASerAgredado.subarbol,sizeof(elemArbol));//aca se cargo el data del nivel que se empieza
    ElementoASerAgredado.dominio = (char*) malloc( (sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN) );
    strncpy(ElementoASerAgredado.dominio,sliceofDomino,(sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN));
    if (L_Vacia(*Subdominios)==FALSE)
        ElementoASerAgredado.data=NULL;
    else
        //ElementoASerAgredado.data = dato;
    {
        ElementoASerAgredado.data = malloc ( tamDato );
        memcpy( ElementoASerAgredado.data, dato, tamDato );
    }

    ABO_InsertarOrdenado(&subarbol.subarbol, fptr, &ElementoASerAgredado );
    for(i=nivel;i>1;i--){
    L_Elem_Cte(subarboles,&arbol);
    L_Borrar_Cte(&subarboles);
    ABO_ModifCte(&arbol.subarbol,&subarbol);
    i--;
    if (i>1)
        {
        L_Elem_Cte(subarboles,&subarbol);
        L_Borrar_Cte(&subarboles);
        ABO_ModifCte(&subarbol.subarbol,&arbol);
        }
    }
    if (nivel%2==0)
    ABO_ModifCte(elTabo,&arbol);
    else ABO_ModifCte(elTabo,&subarbol);
    return PasameUnaListaYUnTaboYYoLoOrdenoNivel3(elTabo,Subdominios, dato,nivel+1, tamDato);
}

int PasameUnaListaYUnTaboYYoLoOrdenoNivel2(TABO* elTabo, TListaSimple* Subdominios, void* dato, size_t tamDato)
{
    char* sliceofDomino;
    elemArbol ElementoASerAgredado, subarbol;
    taboCmp fptr = &DNS_Comparar;


    if (L_Vacia(*Subdominios)==TRUE )return TRUE;
    ABO_ElemCte(*elTabo,&subarbol);
    L_Mover_Cte(Subdominios,L_Primero);
    L_Elem_Cte(*Subdominios,&sliceofDomino);
    L_Borrar_Cte(Subdominios);

    ABO_Crear(&ElementoASerAgredado.subarbol,sizeof(elemArbol));//aca se cargo el data del nivel que se empieza
    ElementoASerAgredado.dominio = (char*) malloc( (sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN) );
    strncpy(ElementoASerAgredado.dominio,sliceofDomino,(sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN));
    if (L_Vacia(*Subdominios)==FALSE)
        ElementoASerAgredado.data=NULL;
    else
        //ElementoASerAgredado.data = dato;
    {
        ElementoASerAgredado.data = malloc ( tamDato );
        memcpy( ElementoASerAgredado.data, dato, tamDato );
    }

    ABO_InsertarOrdenado(&subarbol.subarbol, fptr, &ElementoASerAgredado );
    ABO_ModifCte(elTabo,&subarbol);

    return PasameUnaListaYUnTaboYYoLoOrdenoNivel3(elTabo,Subdominios, dato,2, tamDato);
}



int PasameUnaListaYUnTaboYYoLoOrdeno(TABO* elTabo, TListaSimple* Subdominios, void* dato, size_t tamDato)
{
    char* sliceofDomino;
    elemArbol ElementoASerAgredado;
    taboCmp fptr = &DNS_Comparar;

    if (L_Vacia(*Subdominios)==TRUE )return TRUE;

    L_Mover_Cte(Subdominios,L_Primero);
    L_Elem_Cte(*Subdominios,&sliceofDomino);
    L_Borrar_Cte(Subdominios);

    ABO_Crear(&ElementoASerAgredado.subarbol,sizeof(elemArbol));
    ElementoASerAgredado.dominio = (char*) malloc( (sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN) );
    strncpy(ElementoASerAgredado.dominio,sliceofDomino,(sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN));
    if (L_Vacia(*Subdominios)==FALSE)
        ElementoASerAgredado.data=NULL;
    else
        //ElementoASerAgredado.data = dato;
    {
        ElementoASerAgredado.data = malloc ( tamDato );
        memcpy( ElementoASerAgredado.data, dato, tamDato );
    }

    ABO_InsertarOrdenado( elTabo, fptr, &ElementoASerAgredado );
    return PasameUnaListaYUnTaboYYoLoOrdenoNivel2(elTabo,Subdominios, dato, tamDato);

}


int agregarDominio( TDADNS* dns, char* dominio, void* dato ){
    /**pasos:
    *reviso que exista la lista con la ultima parte del dominio
    *si no existe la inserto ordenadamente y luego lo que quede del dominio
    *si existe busco en el arbol donde iria y lo inserto.
    */
    char* sliceofDomino;
    int menor=TRUE,mover=TRUE,pasada=0;
    elemArbol ElementoDeLaEstructura;
    TListaSimple Subdominios;
    int iguales=FALSE;

    if (ERROR==parsearDominio(dominio,&Subdominios, DNS_Usar)) return ERROR;

    L_Mover_Cte(&Subdominios,L_Primero);
    L_Elem_Cte(Subdominios,&sliceofDomino);

    if(L_Vacia(dns->dominios)==FALSE)
    {
        L_Mover_Cte(&(dns->dominios),L_Primero);
        while((mover==TRUE)&&(menor==TRUE))
        {
            if(pasada>0/**si no es la primera vez*/)
                mover=L_Mover_Cte(&(dns->dominios),L_Siguiente);

            if (mover==TRUE)
            {
                L_Elem_Cte(dns->dominios,&ElementoDeLaEstructura);

                if (strcmp(ElementoDeLaEstructura.dominio,sliceofDomino)>=0){
                    menor=FALSE;
                    if (strcmp(ElementoDeLaEstructura.dominio,sliceofDomino)>=0)
                        iguales=TRUE;
                }

                pasada++;
            }
        }
    }

    L_Borrar_Cte(&Subdominios);  //TODO no se borra, se pasa al siguiente!

    /**ya esta creado el elemento de la lista. ahora es agregar ordenado. existia y tengo que buscar dentro del arbol*/
    if ((L_Vacia(dns->dominios)==TRUE)||(strcmp(ElementoDeLaEstructura.dominio,sliceofDomino)!=0)){
        /**en caso de que no existiese el .com o lo q sea lo tengo q crear antes de pasarlo*/
   // free(ElementoDeLaEstructura.dominio);
    ElementoDeLaEstructura.dominio = (char*) malloc( (sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN) );
    strncpy(ElementoDeLaEstructura.dominio,sliceofDomino,(sizeof(char))*(strlen(sliceofDomino)+CSTR_FIN));
    ABO_Crear(&ElementoDeLaEstructura.subarbol, sizeof(elemArbol));
    }

    PasameUnaListaYUnTaboYYoLoOrdeno(&ElementoDeLaEstructura.subarbol,&Subdominios,dato, dns->tamanio);

    if (iguales==TRUE){
        L_Modificar_Cte(dns->dominios,&ElementoDeLaEstructura);
    }
    else
    {
        if(menor==TRUE)
            L_Insertar_Cte(&(dns->dominios),L_Siguiente,&ElementoDeLaEstructura);
        else if (menor==FALSE)
            L_Insertar_Cte(&(dns->dominios),L_Anterior,&ElementoDeLaEstructura);
    }

    return TRUE;
}








